package com.nexus.all.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.nexus.all.constants.RedisKeyNexus;
import com.nexus.all.dto.NoteContentDTO;
import com.nexus.all.dto.NoteDTO;
import com.nexus.all.dto.UserChooseDTO;
import com.nexus.all.enums.AiOperateEnum;
import com.nexus.all.manager.*;
import com.nexus.all.model.*;
import com.nexus.all.service.AiService;
import com.nexus.all.service.NoteService;
import com.nexus.bean.utils.AesUtils;
import com.nexus.bean.utils.CollectionsUtil;
import com.nexus.bean.utils.PasswordEncoderUtil;
import com.nexus.bean.utils.StringUtils;
import com.nexus.oss.service.OssService;
import com.nexus.redis.utils.RedisUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@AllArgsConstructor
public class AiServiceImpl implements AiService {

    private final UserManager userManager;
    private final AiChooseManager aiChooseManager;
    private final PasswordEncoderUtil passwordEncoderUtil;
    private final UserTimeMailManager userTimeMailManager;
    private final NoteService noteService;
    private final OssService ossService;

    @Override
    @DSTransactional
    public String autoReply(String wxOpenId, String content) {
        log.info("开始识别自动回复处理:{}", content);

        if (StringUtils.isEmpty(content) || content.equals("0")) {
            RedisUtil.delete(RedisKeyNexus.getAiUserChoose(wxOpenId));
            return getMenu(null);
        }

        User user = userManager.getByWxOpenId(wxOpenId);

        Object o = RedisUtil.get(RedisKeyNexus.getAiUserChoose(wxOpenId));
        UserChooseDTO userChooseDTO = null;
        if (Objects.nonNull(o)) {
            userChooseDTO = JSON.parseObject(o.toString(), UserChooseDTO.class);
        }

        /**
         * 绑定校验
         */
        if (Objects.isNull(userChooseDTO)) {
            if (!content.equals("1") && Objects.isNull(user)) {
                return getMenu("你得先绑定账号，不然我都不知道你是谁啊！");
            }
        } else {
            if (!userChooseDTO.getChooseId().equals(1L) && Objects.isNull(user)) {
                return getMenu("你得先绑定账号，不然我都不知道你是谁啊！");
            }
        }

        if (Objects.isNull(userChooseDTO)) {
            /**
             * 用户需要选择选项
             */
            return selectOptions(wxOpenId, content, user);
        } else {
            /**
             * 用户需要回答答案
             */
            return answerTheAnswer(wxOpenId, content, userChooseDTO, user);
        }
    }

    /**
     * 选择选项
     *
     * @param wxOpenId 用户标识
     * @param content  做出的选项
     * @param user
     * @return
     */
    private String selectOptions(String wxOpenId, String content, User user) {
        Long chooseId = null;
        try {
            //回答的不是数字
            chooseId = Long.parseLong(content);
        } catch (Exception e) {
            return getMenu("眼不好使吗，选序号 三个字看不到吗？\n能不能行啊？？\n回复序号的数字，ok不？？？");
        }
        AiChoose aiChoose = aiChooseManager.getById(chooseId);
        if (Objects.isNull(aiChoose)) {
            return getMenu("就是说，我给你这个选项了吗？\n你考试A、B、C、D四个答案选个E？？");
        }
        //选项是否需要回答
        if (aiChoose.getIsNeedReply()) {
            //如果用户选的是绑定账号，判断是否绑定过
            if (chooseId.equals(1L) && Objects.nonNull(user)) {
                return getMenu("你是不是忘了你已经绑定过了？你是鱼吗？记忆就七秒？");
            }
            UserChooseDTO userChooseDTO = new UserChooseDTO();
            userChooseDTO.setReplyValue(JSON.toJSONString(new HashMap<>()));
            userChooseDTO.setChooseId(aiChoose.getId());
            //当前选项正在回答的问题序号
            userChooseDTO.setSortNum(1);
            //记录用户需要回答的选项
            RedisUtil.set(RedisKeyNexus.getAiUserChoose(wxOpenId), JSON.toJSONString(userChooseDTO), TimeUnit.DAYS, 30);

            //获取第一个问题让用户回答
            AiChoose nextAiChoose = aiChooseManager.getNextChoose(chooseId, 1);
            if (Objects.isNull(nextAiChoose)) {
                //没有配置问题
                return dealResult(chooseId, wxOpenId, user, null);
            }
            return nextAiChoose.getAiChoose();
        } else {
            //继续让用户选择下一级选项
            List<AiChoose> aiChooseList = aiChooseManager.getNextChooseList(chooseId);
            if (CollectionsUtil.isEmpty(aiChooseList)) {
                return getMenu("emmmm，这个功能我忘了\n你去试试别的吧，输入“0”重新选择");
            }
            StringBuilder builder = new StringBuilder();
            builder.append("请输入序号选择：");
            builder.append("\n");
            builder.append("序号\t\t\t选项");
            for (AiChoose nextAiChoose : aiChooseList) {
                builder.append("\n");
                builder.append(nextAiChoose.getId() + "\t\t\t" + nextAiChoose.getAiChoose());
            }
            return builder.toString();
        }
    }

    /**
     * 回答答案
     *
     * @param wxOpenId      用户标识
     * @param content       本地回答内容
     * @param userChooseDTO 用户的选项和历史回答内容
     * @param user          用户信息
     * @return
     */
    private String answerTheAnswer(String wxOpenId, String content, UserChooseDTO userChooseDTO, User user) {
        AiChoose aiChoose = aiChooseManager.getByParentIdAndSortNum(userChooseDTO.getChooseId(), userChooseDTO.getSortNum());
        //问题下级还未拓展新的问题
        if (Objects.isNull(aiChoose)) {
            return getMenu("抱歉，我的记忆错乱了\t你去试试别的吧");
        }

        //获取用户之前的回答记录
        Map<String, String> map = JSON.parseObject(userChooseDTO.getReplyValue(), Map.class);
        //记录用户最新的回答
        map.put(aiChoose.getAiChooseKey(), content);

        //将回答记录落库
        userChooseDTO.setReplyValue(JSON.toJSONString(map));
        userChooseDTO.setSortNum(userChooseDTO.getSortNum() + 1);
        RedisUtil.set(RedisKeyNexus.getAiUserChoose(wxOpenId), JSON.toJSONString(userChooseDTO), TimeUnit.DAYS, 30);

        //获取下一个问题
        AiChoose nextAiChoose = aiChooseManager.getNextChoose(userChooseDTO.getChooseId(), userChooseDTO.getSortNum());

        //没有下一个问题，回答结束，开始分析处理结果
        if (Objects.isNull(nextAiChoose)) {
            return dealResult(userChooseDTO.getChooseId(), wxOpenId, user, map);
        }

        /*if (OptionsValueEnum.GET_CONTENT_TYPE.equal(nextAiChoose.getOptionsEnumValue())) {
            //文案类型
            List<ContentTypeApiVO> contentTypeApiVOList = contentClient.getContentTypeList();
            Map<Long, String> optionMaps = Optional.ofNullable(contentTypeApiVOList).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(ContentTypeApiVO::getId, ContentTypeApiVO::getTypeName));

            return returnOptions("请选择文案类型序号", optionMaps);
        } else if (OptionsValueEnum.GET_SHARE_USER.equal(nextAiChoose.getOptionsEnumValue())) {
            //共享用户
            List<User> list = userManager.list();
            List<User> userList = list.stream().filter((inUser) -> {
                return !inUser.getId().equals(user.getId());
            }).collect(Collectors.toList());
            Map<Long, String> optionMaps = userList.stream().collect(Collectors.toMap(User::getId, User::getNickName));
            return returnOptions("请选择共享的用户序号（输入”00“为不共享）", optionMaps);
        }*/

        //继续回答
        return nextAiChoose.getAiChoose();
    }

    /**
     * 处理用户的回答
     *
     * @param chooseId 当前回答的选项
     * @param wxOpenId 微信openId
     * @param user     用户信息
     * @param map      历史回答记录
     * @return
     */
    private String dealResult(Long chooseId, String wxOpenId, User user, Map<String, String> map) {

        //清除用户做的选择
        RedisUtil.delete(RedisKeyNexus.getAiUserChoose(wxOpenId));

        AiChoose aiChoose = aiChooseManager.getById(chooseId);
        Byte chooseEnum = Byte.parseByte(aiChoose.getAiChooseKey());
        if (!AiOperateEnum.exists(chooseEnum)) {
            return getMenu("emmmm，这个功能我忘了\n你去试试别的吧");
        }

        if (AiOperateEnum.BIND_COUNT.equal(chooseEnum)) {
            String userName = map.get("userName");
            String passWord = map.get("passWord");
            User existUser = userManager.getByUserName(userName);
            if (Objects.isNull(existUser)) {
                return getMenu("我不记得我有创建这个账号啊，你再想想吧");
            }
            boolean matches = passwordEncoderUtil.matches(passWord, existUser.getUserPwd());
            if (!matches) {
                return getMenu("密码错了，我真服了你这个老六");
            }
            userManager.bindWxOpenIdByUserName(userName, wxOpenId);
            return getMenu("恭喜你绑定失败(骗你的，绑定成功了！)");
        } else if (AiOperateEnum.CREATE_NOTE.equal(chooseEnum)) {
            String noteImg = map.get("noteImg");
            if (!noteImg.contains("http:")) {
                return getMenu("没有检测到正确的封面呢，请重新上传！");
            }
            noteImg = ossService.uploadImageByUrl(noteImg);
            NoteDTO noteDTO = new NoteDTO();
            noteDTO.setCoverUrl(noteImg);
            noteDTO.setTitle(map.get("noteTitle"));
            noteDTO.setUserId(user.getId());
            NoteContentDTO noteContentdto = new NoteContentDTO();
            noteContentdto.setContent(map.get("noteContent"));
            noteContentdto.setContentIms(noteImg);
            noteDTO.setNoteContentDTO(noteContentdto);
            noteService.addNote(noteDTO);
            return getMenu("发布完成！真是个不错的笔记呢~");
        } else if (AiOperateEnum.GET_NOT_SENT_MAIL.equal(chooseEnum)) {
            List<UserTimeMail> userTimeMailList = userTimeMailManager.getUserNotSendMail(user.getId());
            StringBuilder builder = new StringBuilder();
            builder.append("待发送邮件标题\t\t接收邮箱\t\t发送时间");
            if (CollectionsUtil.isEmpty(userTimeMailList)) {
                builder.append("\n");
                builder.append("暂无记录\t\t暂无记录\t\t暂无记录");
                return getMenu(builder.toString());
            }
            for (UserTimeMail record : userTimeMailList) {
                builder.append("\n");
                builder.append(record.getContentTitle() + "\t\t" + record.getSendMail() + "\t\t" + record.getSendTime());
            }
            return getMenu(builder.toString());
        } else if (AiOperateEnum.ADD_USER_TIME_MAIL.equal(chooseEnum)) {
            UserTimeMail userTimeMail = new UserTimeMail();
            userTimeMail.setUserId(user.getId());
            //生成加密盐值
            userTimeMail.setContentSalt(UUID.randomUUID().toString().replaceAll("-", ""));
            //使用Aes进行加密存储
            userTimeMail.setContent(AesUtils.encryption(map.get("content"), userTimeMail.getContentSalt()));
            userTimeMail.setContentTitle(map.get("contentTitle"));
            userTimeMail.setSendMail(map.get("sendMail"));
            LocalDateTime sendTime = null;
            try {
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-M-d H:m:s");
                sendTime = LocalDateTime.parse(map.get("sendTime"), df);
            } catch (Exception e) {
                return getMenu("发送时间格式应该为 2024-01-01 01:01:01");
            }
            userTimeMail.setSendTime(sendTime);
            userTimeMailManager.save(userTimeMail);
            return getMenu("任务设置成功~");
        }

        return getMenu("这个功能点我忘了欸");
    }

    private String returnOptions(String headStr, Map<Long, String> optionMaps) {
        StringBuilder builder = new StringBuilder();
        builder.append(headStr);
        builder.append("\n");
        builder.append("序号\t\t\t选项");
        for (Map.Entry<Long, String> entry : optionMaps.entrySet()) {
            builder.append("\n");
            builder.append(entry.getKey() + "\t\t\t" + entry.getValue());
        }
        return builder.toString();
    }


    /**
     * 获取一级菜单
     *
     * @param message
     * @return
     */
    private String getMenu(String message) {
        List<AiChoose> aiChooseList = aiChooseManager.getByLevel(0);
        StringBuilder builder = new StringBuilder();
        if (StringUtils.isNotBlank(message)) {
            builder.append(message);
            builder.append("\n");
            builder.append("\n");
        }
        builder.append("请输入序号选择：");
        builder.append("\n");
        builder.append("序号\t\t\t选项");
        for (AiChoose aiChoose : aiChooseList) {
            builder.append("\n");
            builder.append(aiChoose.getId() + "\t\t\t" + aiChoose.getAiChoose());
        }
        return builder.toString();
    }
}
